package com.tarena.lbs.basic.web.service;

import com.github.pagehelper.PageInfo;
import com.tarena.lbs.attach.api.AttachApi;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.web.event.output.BasicOutputSource;
import com.tarena.lbs.basic.web.repository.AdminRepository;
import com.tarena.lbs.basic.web.repository.StoreRepository;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.common.security.utils.LbsSecurityContenxt;
import com.tarena.lbs.pojo.attach.param.PicUpdateParam;
import com.tarena.lbs.pojo.basic.entity.StoreSearchEntity;
import com.tarena.lbs.pojo.basic.event.LocationStoreEvent;
import com.tarena.lbs.pojo.basic.param.StoreParam;
import com.tarena.lbs.pojo.basic.param.UserLocationParam;
import com.tarena.lbs.pojo.basic.po.AdminPO;
import com.tarena.lbs.pojo.basic.po.StorePO;
import com.tarena.lbs.pojo.basic.query.AreaStoreQuery;
import com.tarena.lbs.pojo.basic.query.StoreQuery;
import com.tarena.lbs.pojo.basic.vo.StoreVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class StoreService {
    @Autowired
    private BasicOutputSource outputSource;
    @Autowired
    private AdminRepository adminRepository;
    @Autowired
    private StoreRepository storeRepository;
    @DubboReference
    private AttachApi attachApi;
    public PageResult<StoreVO> storePages(StoreQuery storeQuery) throws BusinessException {
        //1 那登录认证对象
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        //2 不存在 断言异常
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","认证用户失败"));
        Roles role=userPrinciple.getRole();
        Integer adminId=userPrinciple.getId();
        //3 SHOP角色 查询当前用户的businessId 封装 where business_id=#{}
        if (role==Roles.SHOP){
            //4 查询adminId对应详情 封装query中的businessId
            AdminPO adminPO = adminRepository.getAdminById(adminId);
            storeQuery.setBusinessId(adminPO.getBusinessId());
        }
        //5 仓储层查询 分装分页
        PageInfo<StorePO> poPageInfo=storeRepository.getStoresByPage(storeQuery);
        PageResult<StoreVO> voPages=new PageResult<>();
        voPages.setPageNo(poPageInfo.getPageNum());
        voPages.setPageSize(poPageInfo.getPageSize());
        voPages.setTotal(poPageInfo.getTotal());
        List<StoreVO> vos=null;
        if (poPageInfo.getTotal()>0){
            vos=poPageInfo.getList().stream().map(po->{
                StoreVO vo=new StoreVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPages.setObjects(vos);
        return voPages;
    }

    public void storeSave(StoreParam param) {
        //1.验证businessId UNDO
        //2.验证provinceId cityId areaId是否合法 UNDO
        //3.封装完整数据 写入仓储层数据库和es
        //转化拷贝
        StorePO poParam=new StorePO();
        BeanUtils.copyProperties(param,poParam);
        //补充数据
        poParam.setStoreLatitude(param.getLatitude());
        poParam.setStoreLongitude(param.getLongitude());
        poParam.setStoreStatus(0);//初始化 启用0 禁用1
        poParam.setCreateTime(new Date());
        poParam.setUpdateTime(poParam.getCreateTime());
        storeRepository.saveStore(poParam);
        //4.绑定图片 所需的业务数据 练习时间
        Integer businessId=poParam.getId();
        Integer storeLogo=300;
        Integer storeImages=400;
        List<PicUpdateParam> params=new ArrayList<>();
        //先封装logo
        PicUpdateParam logoParam=new PicUpdateParam();
        logoParam.setBusinessId(businessId);
        logoParam.setBusinessType(storeLogo);
        logoParam.setId(Integer.valueOf(poParam.getStoreLogo()));
        params.add(logoParam);
        List<String> storeImagesIds = param.getStoreImagesIds();
        for (String storeImagesId : storeImagesIds) {
            PicUpdateParam picUpdateParam=new PicUpdateParam();
            picUpdateParam.setBusinessId(businessId);
            picUpdateParam.setBusinessType(storeImages);
            picUpdateParam.setId(Integer.valueOf(storeImagesId));
            params.add(picUpdateParam);
        }
        try {
            boolean result = attachApi.batchUpdateBusiness(params);
            if (!result){
                throw new BusinessException("-2","图片绑定失败");
            }
        }catch (Exception e){
            log.error("图片绑定失败",e);
        }
    }

    public PageResult<StoreVO> getCityStores(AreaStoreQuery areaStoreQuery) throws BusinessException {
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","认证用户失败"));
        //利用user的id值查询admin详情
        AdminPO adminPO = adminRepository.getAdminById(userPrinciple.getId());
        Asserts.isTrue(adminPO==null,new BusinessException("-2","不存在用户"));
        Integer businessId=adminPO.getBusinessId();
        //传递给仓储层 条件2个 businessId的值 还有query listId
        PageInfo<StorePO> poPageInfo=storeRepository.getStoresByAreasAndBizId(businessId,areaStoreQuery);
        PageResult<StoreVO> voPages=new PageResult<>();
        voPages.setPageNo(poPageInfo.getPageNum());
        voPages.setPageSize(poPageInfo.getPageSize());
        voPages.setTotal(poPageInfo.getTotal());
        List<StoreVO> vos=null;
        if (poPageInfo.getTotal()>0){
            vos=poPageInfo.getList().stream().map(po->{
                StoreVO vo=new StoreVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPages.setObjects(vos);
        return voPages;
    }

    public void locationReport(UserLocationParam param) throws BusinessException {
        //1.当前登录用户是谁 和查询范围内店铺没有关系 和 marketing处理的逻辑有关
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","认证用户失败"));
        //必须是手机端小程序用户
        Asserts.isTrue(userPrinciple.getRole()!=Roles.USER,new BusinessException("-2","当前用户不是门店用户"));
        log.info("用户开始定位店铺数据:{}",userPrinciple.getNickname());
        //2.查询范围5公里之内的所有店铺信息
        List<StoreSearchEntity> entities=storeRepository.getLocationStores(param);
        //3.如何发送消息 如果组织消息内容 考虑消费者所需的数据 包含userId storeIds(定位所有店铺ids)
        //先组织一个即将发送的消息数据message 包赚的是本次业务消息事件
        LocationStoreEvent locationStoreEvent=new LocationStoreEvent();
        if (CollectionUtils.isEmpty(entities)){
            log.info("当前定位上报用户:{},定位地理位置:{},没有发现店铺",userPrinciple.getNickname(),param);
        }else{
            log.info("用户:{},定位店铺数据:{}",userPrinciple.getNickname(),entities);
            locationStoreEvent.setUserId(userPrinciple.getId());
            List<Integer> storeIds = entities.stream().map(entity -> {
                return entity.getId();
            }).collect(Collectors.toList());
            locationStoreEvent.setStoreIds(storeIds);
            log.info("发送消息数据:{}",locationStoreEvent);
            Message<LocationStoreEvent> message = MessageBuilder.withPayload(locationStoreEvent).build();
            //发送消息事件
            outputSource.locationStoresOutput().send(message);
        }

    }
}






















